package com.trinh.utils.crypto.cryptors;

import com.trinh.utils.crypto.config.KeyConfig;
import com.trinh.utils.crypto.enu.Algorithm;
import com.trinh.utils.crypto.enu.CharFormater;
import com.trinh.utils.crypto.enu.Padding;

import javax.crypto.Cipher;

import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;


/**
 * @Author: TrinhRae
 * @Package: com.trinh.utils.crypto.rsa
 * @Project: generaltools
 * @Date: 2025/6/23 9:28
 */
public class RSAUtil {
    private KeyConfig keyConfig;
    private Algorithm algorithm;
    private Padding padding;
    private CharFormater keyCharFormater;

    public RSAUtil(KeyConfig keyConfig) {
        this.keyConfig = keyConfig;
        this.algorithm = Algorithm.RSA_ECB;
        this.padding = Padding.PKCS1;
    }

    public RSAUtil(KeyConfig keyConfig, Algorithm algorithm, Padding padding, CharFormater keyCharFormater) {
        this.keyConfig = keyConfig;
        this.algorithm = algorithm;
        this.padding = padding;
        this.keyCharFormater = keyCharFormater;
    }

    /**
     * 公钥加密
     */

    public String encrypt(String content) throws Exception {
        PublicKey publicKey = getPublicKeyFromBase64(keyConfig.getPublicKey());
        Cipher cipher = Cipher.getInstance(algorithm.getTransformation(padding));
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] result = cipher.doFinal(content.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(result);
    }

    /**
     * 私钥解密
     */

    public String decrypt(String encrypted) throws Exception {
        PrivateKey privateKey = getPrivateKeyFromBase64(keyConfig.getPrivateKey());
        Cipher cipher = Cipher.getInstance(algorithm.getTransformation(padding));
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(encrypted));
        return new String(decrypted, StandardCharsets.UTF_8);
    }

    /**
     * 从 Base64 编码恢复公钥对象
     */
    public PublicKey getPublicKeyFromBase64(String base64Key) throws Exception {
        byte[] keyBytes = Base64.getDecoder().decode(base64Key);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        return KeyFactory.getInstance("RSA").generatePublic(keySpec);
    }

    /**
     * 从 Base64 编码恢复私钥对象
     */
    public PrivateKey getPrivateKeyFromBase64(String base64Key) throws Exception {
        byte[] keyBytes = Base64.getDecoder().decode(base64Key);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        return KeyFactory.getInstance("RSA").generatePrivate(keySpec);
    }

    /**
     * 私钥签名（SHA256withRSA）
     */
    public String sign(String data) throws Exception {
        PrivateKey privateKey = getPrivateKeyFromBase64(keyConfig.getPrivateKey());
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initSign(privateKey);
        signature.update(data.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(signature.sign());
    }

    /**
     * 公钥验签
     */
    public boolean verify(String data, String signatureStr) throws Exception {
        PublicKey publicKey = getPublicKeyFromBase64(keyConfig.getPublicKey());
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initVerify(publicKey);
        signature.update(data.getBytes(StandardCharsets.UTF_8));
        return signature.verify(Base64.getDecoder().decode(signatureStr));
    }

}